﻿#include "PTWindowImpl.h"
#include <assert.h>

inline PTWWindowImpl::PTWWindowImpl()
{
	m_hWindow_Cache = NULL;

	//OutputEventCallback
	m_pOutputEventCallback_UserData = NULL;
	m_pOutputEventCallback = NULL;
	//InputEventCallback
	m_pInputEventCallback_UserData = NULL;
	m_pInputEventCallback = NULL;

	//To Do  Really??? Memory Barrier m_pOutputCallback m_pInputCallback

	m_pEnv_Cache = NULL;
	m_rActivity_Cache = NULL;

	//HookMessagePump
	int hSocketReadAndWrite[2];
	int iResult = ::socketpair(AF_UNIX, SOCK_STREAM, 0, hSocketReadAndWrite);
	assert(iResult == 0);
	m_hSocketRead = hSocketReadAndWrite[0];
	m_hSocketWrite = hSocketReadAndWrite[1];
}

inline PTWWindowImpl::~PTWWindowImpl()
{

}

void PTWWindowImpl::InputEventCallback_Hook(void *pUserData, void(PTPTR *pInputEventCallback)(void *pUserData, void *pInputData))
{
	m_pInputEventCallback_UserData = pUserData;
	//To Do MemoryBarrier pUserData先于pCallback
	m_pInputEventCallback = pInputEventCallback;
}

void PTWWindowImpl::OutputEventCallback_Hook(void *pUserData, void(PTPTR *pOutputEventCallback)(void *pUserData, void *pOutputData))
{
	m_pOutputEventCallback_UserData = pUserData;
	//To Do MemoryBarrier pUserData先于pCallback
	m_pOutputEventCallback = pOutputEventCallback;

	//串行 With Java_org_PatriotEngine_Runtime_PTWindowImpl_OnNativeWindowCreated
	//HookMessagePump_ALooperCallback
	//ALOOPER_EVENT_INPUT
	uint32_t PTCommandType = PTCommandType_OutputEventCallback_Hook;
	ssize_t ssResult = ::send(m_hSocketWrite, &PTCommandType, sizeof(PTCommandType), 0);
	assert(ssResult == sizeof(uint32_t));
}

#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <android/looper.h>

void PTWWindowImpl::HookMessagePump()
{
	ALooper* pLooper = ::ALooper_forThread();
	assert(pLooper != NULL);

	int ID_TermminateMessagePump = 0XEEEEEEEE;
	int iResult = ::ALooper_addFd(pLooper, m_hSocketRead, ID_TermminateMessagePump, ALOOPER_EVENT_INPUT, &HookMessagePump_ALooperCallback, this);
	assert(iResult == 1);
}

int PTWWindowImpl::HookMessagePump_ALooperCallback(int hSocketRead, int, void *pData)
{
	PTWWindowImpl *pWindow = static_cast<PTWWindowImpl *>(pData);

	uint32_t PTCommandType;
	ssize_t ssResult = ::recv(hSocketRead, &PTCommandType, sizeof(PTCommandType), 0);
	assert(ssResult == sizeof(uint32_t));

	switch (PTCommandType)
	{
	case PTCommandType_OutputEventCallback_Hook:
	{
		if (pWindow->m_hWindow_Cache != NULL)
		{
			struct
			{
				uint32_t m_Type;
				PTWHDisplay m_hDisplay;
				PTWHWindow m_hWindow;
				uint32_t m_Width;
				uint32_t m_Height;
			}OutputEventData;
			OutputEventData.m_Type = PTWWindowImpl::PTOutputEventType_WindowCreated;
			OutputEventData.m_hDisplay = NULL;
			OutputEventData.m_hWindow = pWindow->m_hWindow_Cache;
			OutputEventData.m_Width = static_cast<uint32_t>(::ANativeWindow_getWidth(pWindow->m_hWindow_Cache));
			OutputEventData.m_Height = static_cast<uint32_t>(::ANativeWindow_getHeight(pWindow->m_hWindow_Cache));

			assert(pWindow->m_pOutputEventCallback != NULL);
			pWindow->m_pOutputEventCallback(pWindow->m_pOutputEventCallback_UserData, &OutputEventData);
		}
	}
	return 1;
	case PTCommandType_TermminateMessagePump:
	{
		//TermminateMessagePump

		//Write End Close
		bool bIsEOF;
		ssize_t ssResult = ::recv(hSocketRead, &bIsEOF, sizeof(bIsEOF), 0);
		assert(ssResult == 0);

		int iResult = ::close(hSocketRead);
		assert(iResult == 0);

		//Activity::finish
		if (pWindow->m_rActivity_Cache != NULL)
		{
			jclass rClassActivity = pWindow->m_pEnv_Cache->GetObjectClass(pWindow->m_rActivity_Cache);
			jmethodID idMethodFinish = pWindow->m_pEnv_Cache->GetMethodID(rClassActivity, "finish", "()V");
			pWindow->m_pEnv_Cache->CallVoidMethodA(pWindow->m_rActivity_Cache, idMethodFinish, NULL);

			pWindow->m_pEnv_Cache->DeleteLocalRef(rClassActivity);
			pWindow->m_pEnv_Cache->DeleteWeakGlobalRef(pWindow->m_rActivity_Cache);
		}

		//System::exit
		jclass rClassSystem = pWindow->m_pEnv_Cache->FindClass("java/lang/System");
		jmethodID idMethodExit = pWindow->m_pEnv_Cache->GetStaticMethodID(rClassSystem, "exit", "(I)V");
		jvalue args[1];
		args[0].i = 0;
		pWindow->m_pEnv_Cache->CallStaticVoidMethodA(rClassSystem, idMethodExit, args);

		pWindow->m_pEnv_Cache->DeleteLocalRef(rClassSystem);

	}
	return 0;
	default:
	{
		assert(0);
		return 1;
	}
	}
}

void PTWWindowImpl::TermminateMessagePump()
{
	//HookMessagePump_ALooperCallback
	//ALOOPER_EVENT_HANGUP
	uint32_t PTCommandType = PTCommandType_TermminateMessagePump;
	ssize_t ssResult = ::send(m_hSocketWrite, &PTCommandType, sizeof(PTCommandType), 0);
	assert(ssResult == sizeof(uint32_t));

	int iResult = ::close(m_hSocketWrite);
	assert(iResult == 0);
}

void PTWWindowImpl::Parent_Set(PTWHWindow hWindowParent)
{
	assert(0);
}

void PTWWindowImpl::Position_Set(uint32_t, uint32_t)
{
	assert(0);
}

void PTWWindowImpl::Size_Set(uint32_t, uint32_t)
{
	assert(0);
}

static PTWWindowImpl g_WindowImpl;

#include <android/native_window_jni.h>
extern "C" JNIEXPORT void JNICALL Java_org_PatriotEngine_Runtime_PTWindowImpl_OnNativeWindowCreated(JNIEnv *pEnv, jobject rThis, jobject rSurface)
{
	ANativeWindow *hWindow = ::ANativeWindow_fromSurface(pEnv, rSurface);
	g_WindowImpl.m_hWindow_Cache = hWindow;

	if (g_WindowImpl.m_pOutputEventCallback != NULL)
	{
		struct
		{
			uint32_t m_Type;
			PTWHDisplay m_hDisplay;
			PTWHWindow m_hWindow;
			uint32_t m_Width;
			uint32_t m_Height;
		}OutputEventData;
		OutputEventData.m_Type = PTWWindowImpl::PTOutputEventType_WindowCreated;
		OutputEventData.m_hDisplay = NULL;
		OutputEventData.m_hWindow = hWindow;
		OutputEventData.m_Width = static_cast<uint32_t>(::ANativeWindow_getWidth(hWindow));
		OutputEventData.m_Height = static_cast<uint32_t>(::ANativeWindow_getHeight(hWindow));

		g_WindowImpl.m_pOutputEventCallback(g_WindowImpl.m_pOutputEventCallback_UserData, &OutputEventData);
	}
}

extern "C" JNIEXPORT void JNICALL Java_org_PatriotEngine_Runtime_PTWindowImpl_OnNativeWindowDestroyed(JNIEnv *pEnv, jobject rThis, jobject rSurface)
{
	g_WindowImpl.m_hWindow_Cache = NULL;

	if (g_WindowImpl.m_pOutputEventCallback != NULL)
	{
		struct
		{
			uint32_t m_Type;
		}OutputEventData;
		OutputEventData.m_Type = PTWWindowImpl::PTOutputEventType_WindowDestroyed;

		g_WindowImpl.m_pOutputEventCallback(g_WindowImpl.m_pOutputEventCallback_UserData, &OutputEventData);
	}
}

extern "C" JNIEXPORT void JNICALL Java_org_PatriotEngine_Runtime_PTWindowImpl_OnNativeWindowChanged(JNIEnv *pEnv, jobject rThis, jobject rSurface, jint format, jint width, jint height)
{
	if (g_WindowImpl.m_pOutputEventCallback != NULL)
	{
		struct
		{
			uint32_t m_Type;
			uint32_t m_Width;
			uint32_t m_Height;
		}OutputEventData;
		OutputEventData.m_Type = PTWWindowImpl::PTOutputEventType_WindowResized;
		OutputEventData.m_Width = static_cast<uint32_t>(width);
		OutputEventData.m_Height = static_cast<uint32_t>(height);

		g_WindowImpl.m_pOutputEventCallback(g_WindowImpl.m_pOutputEventCallback_UserData, &OutputEventData);
	}
}

extern "C" JNIEXPORT void JNICALL Java_org_PatriotEngine_Runtime_PTWindowImpl_OnMotionEventDispatch(JNIEnv *pEnv, jobject rThis, jint action, jfloat x, jfloat y, jint pointerIndex)
{
	if (g_WindowImpl.m_pInputEventCallback != NULL)
	{

	}
}

static void *PTInvokeMain(void *pVoid);
static bool g_PTWindowImpl_OnActivityCreated_bFirstTime = true;

extern "C" JNIEXPORT void JNICALL Java_org_PatriotEngine_Runtime_PTWindowImpl_OnActivityCreated(JNIEnv *pEnv, jobject rThis)
{
	if (g_PTWindowImpl_OnActivityCreated_bFirstTime)
	{
		g_WindowImpl.m_pEnv_Cache = pEnv;
	}
	assert(g_WindowImpl.m_pEnv_Cache == pEnv);

	assert(g_WindowImpl.m_rActivity_Cache == NULL);
	g_WindowImpl.m_rActivity_Cache = pEnv->NewWeakGlobalRef(rThis);

	g_WindowImpl.HookMessagePump();

	if (g_PTWindowImpl_OnActivityCreated_bFirstTime)
	{
		bool bResult;
		PTThread hThreadInvoke;
		bResult = ::PTThreadCreate(&PTInvokeMain, static_cast<PTWWindowImpl *>(&g_WindowImpl), &hThreadInvoke);
		assert(bResult);
	}

	g_PTWindowImpl_OnActivityCreated_bFirstTime = false;
}

extern "C" JNIEXPORT void JNICALL Java_org_PatriotEngine_Runtime_PTWindowImpl_OnActivityDestroyed(JNIEnv *pEnv, jobject rThis)
{
	g_WindowImpl.m_pEnv_Cache->DeleteWeakGlobalRef(g_WindowImpl.m_rActivity_Cache);
	g_WindowImpl.m_rActivity_Cache = NULL;
}

#include "../../../Public/Application/PTAExport.h"
static void *PTInvokeMain(void *pVoid)
{
	PTWWindowImpl *pWindow = static_cast<PTWWindowImpl *>(pVoid);

	char CmdLine[] = { "PTLauncher" };
	char *argv[1] = { CmdLine };

	int iResult = ::PTAMain(static_cast<IPTWWindow *>(pWindow), 1, argv);

	pWindow->TermminateMessagePump();

	return reinterpret_cast<void *>(static_cast<intptr_t>(iResult));
}

#if 0

static bool g_IsProcessCreate = true;//标识进程创建，区别于ANativeActivity对象的创建

static PTWindowImpl g_WindowImpl;

struct PTDatagramInputQueue
{
	enum :uintptr_t {
		TAG_INPUTQUEUECREATED,
		TAG_INPUTQUEUEDESTROYED,
		TAG_THREADEXIT
	}m_Tag;
	uintptr_t m_Data;
};
static PTSocket g_hSocketInputQueue;

struct PTParamInputQueue
{
	PTSocket hSocket;
	PTSemaphore hSemaphore;
};
static void * PTMainInputQueue(void *pVoid);
static PTThread g_hThreadInputQueue;

static void *PTInvokeMain(void *);
static PTThread g_hThreadInvoke;

#include <android/native_activity.h>

ANativeActivity * volatile g_pActivity = NULL;
static bool volatile g_IsTerminated = false;

void ANativeActivity_onDestroy(ANativeActivity *);
void ANativeActivity_onInputQueueCreated(ANativeActivity *, AInputQueue *);
void ANativeActivity_onInputQueueDestroyed(ANativeActivity *, AInputQueue *);
void ANativeActivity_onNativeWindowCreated(ANativeActivity *, ANativeWindow *);
void ANativeActivity_onNativeWindowResized(ANativeActivity *, ANativeWindow *);
void ANativeActivity_onNativeWindowDestroyed(ANativeActivity *, ANativeWindow *);

#include <android/looper.h>

#include <unistd.h>//_exit
#include <fcntl.h>
#include <stdio.h>
#include <string.h>

static char g_Internal_DLPath[PATH_MAX];

const char *g_DLPath = g_Internal_DLPath;

//共享库入口点
void ANativeActivity_onCreate(ANativeActivity *pActivity, void *, size_t)
{
	if (g_IsProcessCreate)//进程创建
	{
		g_IsProcessCreate = false;//之后对此函数的回调都只是ANativeActivity对象的创建
		
		//g_DLPath
		{
			g_Internal_DLPath[0] = '\0';

			int hFile = ::open("/proc/self/maps", O_RDONLY);
			assert(hFile != -1);

			FILE *hFileStream = ::fdopen(hFile, "r");
			assert(hFileStream != NULL);

			char PathName[PATH_MAX];//Block
			while (::fscanf(hFileStream,"%s", PathName) != EOF)//::fscanf(hFileStream, "%*s%*s%*s%*s%*s%4096s", pathname) != EOF)
			{
				char *pStringFind = ::strstr(PathName, "libPTWindow.so");
				if (pStringFind != NULL)
				{
					assert((*(pStringFind - 1)) == '/');
					(*pStringFind) = '\0';
					::strcpy(g_Internal_DLPath, PathName);
					break;
				}
			}
			assert(::strlen(g_DLPath) != 0U);

			int iResult = ::fclose(hFileStream);
			assert(iResult == 0);
			//::close(hFile);
		}
	
		::PTSpinLockCreate(&g_SpinLockActivity);
		g_pActivity = pActivity;

		g_WindowImpl.Construct();

		bool bResult;

		PTParamInputQueue ParamInputQueue;
		bResult = ::PTSocketDatagramPair(&ParamInputQueue.hSocket, &g_hSocketInputQueue);
		assert(bResult);
		bResult = ::PTSemaphoreCreate(0U, &ParamInputQueue.hSemaphore);
		assert(bResult);
		bResult = ::PTThreadCreate(PTMainInputQueue, &ParamInputQueue, &g_hThreadInputQueue);
		assert(bResult);
		bResult = ::PTSemaphorePassern(&ParamInputQueue.hSemaphore);
		assert(bResult);
		bResult = ::PTSemaphoreDestory(&ParamInputQueue.hSemaphore);
		assert(bResult);

		bResult = ::PTThreadCreate(&PTMainInvoke, NULL, &g_hThreadInvoke);
		assert(bResult);
	}

	//Terminate
	::PTSpinLockEnterSleep(&g_SpinLockActivity);
	if (g_IsTerminated)
	{
		bool bResult;

		PTDatagramInputQueue DatagramInputQueue;
		DatagramInputQueue.m_Tag = PTDatagramInputQueue::TAG_THREADEXIT;
		DatagramInputQueue.m_Data = NULL;
		PTSocketIOVector SocketIOVector[1];
		SocketIOVector[0].Base = static_cast<void *>(&DatagramInputQueue);
		SocketIOVector[0].Len = sizeof(DatagramInputQueue);
		uint32_t NumberOfBytesWritten[1];
		bResult = ::PTSocketWriteVector(&g_hSocketInputQueue, SocketIOVector, 1U, NumberOfBytesWritten);
		assert(bResult);

		bResult = ::PTThreadWait(&g_hThreadInputQueue);
		assert(bResult);

		bResult = ::PTThreadWait(&g_hThreadInvoke);
		assert(bResult);

		::_exit(0);//unistd.h
	}
	g_pActivity = pActivity;
	::PTSpinLockLeave(&g_SpinLockActivity);

	//只关心进程的生命期而不关心ANativeActivity的生命期
	pActivity->callbacks->onStart = NULL;
	pActivity->callbacks->onResume = NULL;
	pActivity->callbacks->onSaveInstanceState = NULL;
	pActivity->callbacks->onPause = NULL;
	pActivity->callbacks->onStop = NULL;
	pActivity->callbacks->onDestroy = ANativeActivity_onDestroy;

	//callbacks属于ANativeActivity对象的一部分，因此每次回调都需要重新写入，无论是否是进程创建
	pActivity->callbacks->onWindowFocusChanged = NULL;
	pActivity->callbacks->onNativeWindowCreated = ANativeActivity_onNativeWindowCreated;
	pActivity->callbacks->onNativeWindowResized = ANativeActivity_onNativeWindowResized;
	pActivity->callbacks->onNativeWindowRedrawNeeded = NULL;
	pActivity->callbacks->onNativeWindowDestroyed = ANativeActivity_onNativeWindowDestroyed;
	pActivity->callbacks->onInputQueueCreated = ANativeActivity_onInputQueueCreated;
	pActivity->callbacks->onInputQueueDestroyed = ANativeActivity_onInputQueueDestroyed;
	pActivity->callbacks->onContentRectChanged = NULL;
	pActivity->callbacks->onConfigurationChanged = NULL;
	pActivity->callbacks->onLowMemory = NULL;
}

void ANativeActivity_onDestroy(ANativeActivity *)
{
	//Terminate
	::PTSpinLockEnterSleep(&g_SpinLockActivity);
	if (g_IsTerminated)
	{
		bool bResult;

		PTDatagramInputQueue DatagramInputQueue;
		DatagramInputQueue.m_Tag = PTDatagramInputQueue::TAG_THREADEXIT;
		DatagramInputQueue.m_Data = NULL;
		PTSocketIOVector SocketIOVector[1];
		SocketIOVector[0].Base = static_cast<void *>(&DatagramInputQueue);
		SocketIOVector[0].Len = sizeof(DatagramInputQueue);
		uint32_t NumberOfBytesWritten[1];
		bResult = ::PTSocketWriteVector(&g_hSocketInputQueue, SocketIOVector, 1U, NumberOfBytesWritten);
		assert(bResult);

		bResult = ::PTThreadWait(&g_hThreadInputQueue);
		assert(bResult);

		bResult = ::PTThreadWait(&g_hThreadInvoke);
		assert(bResult);

		::_exit(0);//unistd.h
	}
	g_pActivity = NULL;
	::PTSpinLockLeave(&g_SpinLockActivity);
}

void ANativeActivity_onInputQueueCreated(ANativeActivity *, AInputQueue *pInputQueue)
{
	PTDatagramInputQueue DatagramInputQueue;
	DatagramInputQueue.m_Tag = PTDatagramInputQueue::TAG_INPUTQUEUECREATED;
	DatagramInputQueue.m_Data = reinterpret_cast<uintptr_t>(pInputQueue);
	PTSocketIOVector SocketIOVector[1];
	SocketIOVector[0].Base = static_cast<void *>(&DatagramInputQueue);
	SocketIOVector[0].Len = sizeof(DatagramInputQueue);
	uint32_t NumberOfBytesWritten[1];
	bool bResult = ::PTSocketWriteVector(&g_hSocketInputQueue, SocketIOVector, 1U, NumberOfBytesWritten);
	assert(bResult);
}

void ANativeActivity_onInputQueueDestroyed(ANativeActivity *, AInputQueue *pInputQueue)
{
	//在实际测试（目标API级别18）中回调onInputQueueDestroyed从未发生过

	PTDatagramInputQueue DatagramInputQueue;
	DatagramInputQueue.m_Tag = PTDatagramInputQueue::TAG_INPUTQUEUEDESTROYED;
	DatagramInputQueue.m_Data = reinterpret_cast<uintptr_t>(pInputQueue);
	PTSocketIOVector SocketIOVector[1];
	SocketIOVector[0].Base = static_cast<void *>(&DatagramInputQueue);
	SocketIOVector[0].Len = sizeof(DatagramInputQueue);
	uint32_t NumberOfBytesWritten[1];
	bool bResult = ::PTSocketWriteVector(&g_hSocketInputQueue, SocketIOVector, 1U, NumberOfBytesWritten);
	assert(bResult);
}

void ANativeActivity_onNativeWindowCreated(ANativeActivity *, ANativeWindow *HandleWindow)
{
	g_WindowImpl.HandleSet(HandleWindow);
}

void ANativeActivity_onNativeWindowResized(ANativeActivity *, ANativeWindow *HandleWindow)
{
	g_WindowImpl.SizeSet(static_cast<uint32_t>(ANativeWindow_getHeight(HandleWindow)), static_cast<uint32_t>(ANativeWindow_getWidth(HandleWindow)));
}

void ANativeActivity_onNativeWindowDestroyed(ANativeActivity *, ANativeWindow *)
{
	g_WindowImpl.HandleSet(NULL);
}


#include <android/input.h>

inline void PTInputEventProc(AInputEvent *pInputEvent);//应用程序自定义的输入事件处理，类似Win32中的窗口过程

static void * PTMainInputQueue(void *pVoid)
{
	//pthread_setschedparam
	enum {
		ID_SOCKET,
		ID_INPUTQUEUE
	};

	::ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
	{
		PTParamInputQueue *pParam = static_cast<PTParamInputQueue *>(pVoid);
		int AResult = ::ALooper_addFd(ALooper_forThread(), pParam->hSocket.m_fd, ID_SOCKET, ALOOPER_EVENT_INPUT, NULL, NULL);//ALooper内部用poll实现，因此常规的文件描述符也可以和ALooper关联
		assert(AResult != -1);
		bool PTResult = ::PTSemaphoreVrijgeven(&pParam->hSemaphore);
		assert(PTResult);
	}

	bool bLoop = true;
	while (bLoop)
	{
		int ALooper_fd;
		void *ALooper_pData;
		int ALooper_ID = ALooper_pollOnce(-1, &ALooper_fd, NULL, &ALooper_pData);
		switch (ALooper_ID)
		{
		case ID_SOCKET:
		{
			PTDatagramInputQueue SocketDatagram;

			PTSocketIOVector SocketIOVector[1];
			SocketIOVector[0].Base = static_cast<void *>(&SocketDatagram);
			SocketIOVector[0].Len = sizeof(SocketDatagram);
			uint32_t NumberOfBytesRead[1];

			PTSocket hSocket;
			hSocket.m_fd = ALooper_fd;

			bool PTResult = ::PTSocketReadVector(&hSocket, SocketIOVector, 1U, NumberOfBytesRead);
			assert(PTResult);

			switch (SocketDatagram.m_Tag)
			{
			case PTDatagramInputQueue::TAG_INPUTQUEUECREATED:
			{
				AInputQueue *pInputQueue = reinterpret_cast<AInputQueue*>(SocketDatagram.m_Data);
				AInputQueue_attachLooper(pInputQueue, ::ALooper_forThread(), ID_INPUTQUEUE, NULL, static_cast<void *>(pInputQueue));//ALooper允许不同的fd关联同一个ID，ID可用于表示类型
			}
			break;
			case PTDatagramInputQueue::TAG_INPUTQUEUEDESTROYED:
			{
				//在实际测试中，ANativeActivity的onInputQueueDestroyed从未被回调过，存在轻度的内存泄露

				AInputQueue *pInputQueue = reinterpret_cast<AInputQueue*>(SocketDatagram.m_Data);

				//处理AInputQueue对象的弃用
				AInputEvent *pInputEvent;
				while (::AInputQueue_getEvent(pInputQueue, &pInputEvent) >= 0)
				{
					//如果没有对所有非预处理的事件调用AInputQueue_finishEvent并且在handled中传入非0值，那么系统会认为应用程序“未响应”！！！
					if (::AInputQueue_preDispatchEvent(pInputQueue, pInputEvent) == 0)
					{
						::PTInputEventProc(pInputEvent);
						::AInputQueue_finishEvent(pInputQueue, pInputEvent, 1);
					}
				}
				::AInputQueue_detachLooper(pInputQueue);
			}
			break;
			case PTDatagramInputQueue::TAG_THREADEXIT:
			{
				bLoop = false;
			}
			break;
			default:
			{
				assert(0);
			}
			}
			//----------------------------------------------------------------------------------
		}
		break;//----------------------------------------------------------------------------------
		case ID_INPUTQUEUE:
		{
			AInputQueue *pInputQueue = static_cast<AInputQueue *>(ALooper_pData);

			AInputEvent *pInputEvent;
			while (::AInputQueue_getEvent(pInputQueue, &pInputEvent) >= 0)
			{
				//如果没有对所有非预处理的事件调用AInputQueue_finishEvent并且在handled中传入非0值，那么系统会认为应用程序“未响应”！！！
				if (::AInputQueue_preDispatchEvent(pInputQueue, pInputEvent) == 0)
				{
					::PTInputEventProc(pInputEvent);
					::AInputQueue_finishEvent(pInputQueue, pInputEvent, 1);
				}
			}
		}
		break;//----------------------------------------------------------------------------------
		default:
		{
			assert(0);
		}
		}
	}
}

inline void PTInputEventProc(AInputEvent *pInputEvent)
{

}


#include "../../../Public/Main/PTMain.h"

static void *PTMainInvoke(void *)
{
	//PTMain(static_cast<IPTWindow *>(&g_WindowImpl));

	//Terminate
	::PTSpinLockEnterSleep(&g_SpinLockActivity);
	g_IsTerminated = true;
	if (g_pActivity != NULL)
	{
		::ANativeActivity_finish(g_pActivity);
	}
	::PTSpinLockLeave(&g_SpinLockActivity);

	return NULL;
}

#endif